home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 007 / ssedsrc.arc / SSED.C next >
Text File  |  1985-12-11  |  9KB  |  430 lines

  1. #define VERSION "ssed.c 2.2.1 DeSmet 5/20/84\n"
  2. /*
  3.  * (small/stupid) Stream Editor
  4.  * Accepts a,c,d,i commands only
  5.  * commands are on standard input
  6.  * old file is specified
  7.  * edited result is specified file
  8.  * Line numbers are decimal, . and $
  9.  * Modified for DeSmet by Tom Bonfield
  10.  *
  11.  *    Chuck Forsberg
  12.  *    Omen Technology Inc
  13.  *    Rt 1 Box 120v Portland OR 97231
  14.  *    Compuserve: 70715,131
  15.  *
  16.  */
  17.  
  18. /* system dependent stuff */
  19. #include <stdio.h>
  20. #define TRUE 1
  21. #define FALSE 0
  22. #define ERROR (-1)
  23. #define CPMEOF 032
  24. #define MAXINT 32000
  25.  
  26. FILE in, out;
  27.  
  28. #define HUGELINE 1024    /* much easier than crashing if line is too long */
  29. char *aname;        /* name of antecedent file */
  30. char *oname;        /* name of resultant file */
  31. int linno;        /* number of lines that have been output */
  32. int op1,op2;        /* first and (possibly same) last line of cmd */
  33. char crcseen;        /* TRUE if crc given in command line */
  34. unsigned cmdcrc;    /* crc value encountered (decimal) in command line */
  35. unsigned crc;        /* accumulated crc(k) of copied lines from old file */
  36. char cmd, cmdline[HUGELINE],insline[HUGELINE], *axin;
  37.  
  38. char Verbose,Unsqueeze, Ignore;
  39. char cmdeof;        /* EOF (cpmeof) seen on command input */
  40. char ineof;        /* EOF (cpmeof) seen on file input */
  41.  
  42.  
  43. xgetchar()
  44. {
  45.     return fgetc(stdin);
  46. }
  47. int getcr();
  48. int getcin();
  49. int (*getthis)();    /* getchar function for current file */
  50.  
  51. /* Definitions and externals for unsqueezer function */
  52. #define RECOGNIZE 0xFF76    /* unlikely pattern */
  53. /* External declarations for USQ feature */
  54. #define NUMVALS 257    /* 256 data values plus SPEOF*/
  55. /* Decoding tree */
  56. struct {
  57.     int children[2];    /* left, right */
  58. } dnode[NUMVALS - 1];
  59. int bpos;    /* last bit position read */
  60. int curin;    /* last byte value read */
  61. /* Variables associated with repetition decoding */
  62. int repct;    /*Number of times to return value*/
  63. int value;    /*current byte value or EOF */
  64. int inch;
  65.  
  66. getcin()
  67. {
  68.     return getc(in);
  69. }
  70.  
  71. main(argc, argv)
  72. char **argv;
  73. {
  74.     char *cp;
  75.  
  76.     getthis=getcin;
  77.  
  78.     Verbose=Ignore=Unsqueeze=FALSE;
  79.     while (--argc && *(cp = *++argv)=='-') {
  80.  
  81.         while( *++cp) {
  82.             switch(tolower(*cp)) {
  83.             case 'i':
  84.                 Ignore++; break;
  85.             case 'u':
  86.                 Unsqueeze++; break;
  87.             case 'v':
  88.                 Verbose++; break;
  89.             default:    
  90.                 break;
  91.             }
  92.         }
  93.     }
  94.  
  95.     if(argc != 2) {
  96.         fprintf(stderr,VERSION);
  97.         fprintf(stderr,"Usage: ssed [-iuv] infile outfile [<cmdfile]\n");
  98.         fprintf(stderr,"\tEditing commands on stdin\n");
  99.         fprintf(stderr,"\t-i Ignore CRC errors\n");
  100.         fprintf(stderr,"\t-u Unsqueeze infile\n");
  101.         fprintf(stderr,"\t-v Verbose\n");
  102.         exit(1);
  103.     }
  104.  
  105.     if((in=fopen( aname=argv[0], "r")) == NULL) {
  106.         fprintf(stderr, "Can't open %s", aname);
  107.         exit(1);
  108.     }
  109.  
  110.     if((out=fopen( oname=argv[1], "w")) == NULL) {
  111.         fprintf(stderr, "Can't open %s", oname);
  112.         exit(2);
  113.     }
  114.  
  115.     if(Unsqueeze) {
  116.         getthis=getcr;        /* switch getchar function */
  117.         init_usq();        /* initialize unpacking */
  118.     }
  119.  
  120.     linno=1; crc=0;
  121.     cmdeof=ineof=FALSE;
  122.  
  123.     while(getcmd()==FALSE) {
  124.  
  125.         if(cmd == 'a') {
  126.             cmd= 'i'; ++op1;
  127.         }
  128.         if(linno>op1) {
  129.             fprintf(stderr,"At line %d: Can't back up to %d\n",
  130.               linno, op1);
  131.             goto fubar;
  132.         }
  133.         while(linno < op1 && ineof==FALSE)
  134.             copyin();
  135.         if(crcseen && cmdcrc != crc) {
  136.             fprintf(stderr,
  137.               "CRC error on Antecedent File %u should be %u\n",
  138.               crc, cmdcrc);
  139.             fprintf(stderr,
  140.               "'%s' is not the correct Antecedent\n", aname);
  141.             if(!Ignore)
  142.                 exit(1);
  143.         }
  144.         if(cmd != 'i')
  145.             while(op2-- >= linno && ineof==FALSE)
  146.                 chuckline();
  147.         if(cmd=='c' || cmd=='i')
  148.             insert();
  149.         else if(cmd != 'd') {
  150.             fprintf(stderr,"Illegal command %s", cmdline);
  151. fubar:
  152.             fprintf(stderr,
  153.               "Difference file garbled or not made by dif -e\n");
  154.             exit(1);
  155.         }
  156.     }
  157.     while(ineof == FALSE)
  158.         copyin();
  159.     fprintf(stderr,"Ssed finished\n");
  160.     close(out);
  161.     exit(0);
  162. }
  163.  
  164. getcmd()
  165. {
  166.     crcseen=FALSE;
  167.     if(Verbose) {
  168.         cmdcrc=0;
  169.         fprintf(stderr,"%d:", linno);
  170.     }
  171.     if(cmdeof || lgets(cmdline,xgetchar)==0) {
  172.         if(Verbose)
  173.             fprintf(stderr,"EOF on stdin\n");
  174.         return TRUE;
  175.     }
  176.     axin=cmdline;
  177.     op1=op2=getnum();
  178.     if(*axin==',') {
  179.         ++axin, op2=getnum();
  180.     }
  181.     cmd=tolower(*axin++);
  182.     if(*axin++ == ' ') {
  183.         crcseen=TRUE;
  184.         cmdcrc=atoi(axin);
  185.     }
  186.     if(Verbose)
  187.         fprintf(stderr,"%sop1=%d op2=%d cmd=0%o linno=%d cmdcrc=%u\n",
  188.           cmdline, op1, op2, cmd, linno, cmdcrc);
  189.     return FALSE;
  190. }
  191.  
  192. getnum()
  193. {
  194.     int m;
  195.  
  196.     m=0;
  197.     if(*axin=='.') {
  198.         ++axin; return linno;
  199.     }
  200.     if(*axin=='$') {
  201.         ++axin; return MAXINT;
  202.     }
  203.     while(isdigit(*axin))
  204.         m= (m * 10) + (*axin++ - '0');
  205.     return m;
  206. }
  207.  
  208. copyin()
  209. {
  210.     unsigned crck();
  211.     int len;
  212.  
  213.     if((len=lgets(insline,getthis))==0) {
  214.         ineof=TRUE;
  215.         if(Verbose)
  216.             fprintf(stderr,"EOF on old file\n");
  217.         return;
  218.     }
  219.     if(fputs(insline, out)==ERROR) {
  220.         fprintf(stderr,"Write Error");
  221.         exit(1);
  222.     }
  223.     ++linno;
  224.  
  225.     if(--len>0)
  226.         crc += crck(insline, len, 0);
  227. }
  228.  
  229. chuckline()
  230. {
  231.     if(lgets(insline,getthis)==0) {
  232.         if(Verbose)
  233.             fprintf(stderr,"EOF on old file\n");
  234.         ineof=TRUE;
  235.         return;
  236.     }
  237. }
  238.  
  239. insert()
  240. {
  241.     for(;;) {
  242.         if(lgets(insline,xgetchar)==0) {
  243.             fprintf(stderr,"Unexpected EOF on stdin\n");
  244.             cmdeof=TRUE;
  245.             return;
  246.         }
  247.         if(insline[0]=='.' && insline[1]<=015)
  248.             return;
  249.         if(fputs(insline, out)==ERROR) {
  250.             fprintf(stderr,"Write Error");
  251.             exit(1);
  252.         }
  253.         ++linno;
  254.     }
  255. }
  256.  
  257. /* lgets returns length of line read or 0 if eof, gets rid of CR's on input! */
  258. lgets(s, getfnx)
  259. char *s;
  260. int (*getfnx)();
  261. {
  262.     int c;
  263.     char *p;
  264.     p=s;
  265.     for(;;) {
  266.         switch(c= (*getfnx)()) {
  267.         case 015:
  268.             continue;
  269.         case EOF:
  270.         case CPMEOF:
  271.             return 0;
  272.         case 012:
  273.             *p++ = c;
  274.             *p++ = 0;
  275.             return p-s;
  276.         default:
  277.             *p++ = c; continue;
  278.         }
  279.     }
  280. }
  281.  
  282.  
  283.  
  284. /* *** Stuff for first translation module *** */
  285. #define DLE 0x90
  286. /* *** Stuff for second translation module *** */
  287. #define SPEOF 256    /* special endfile token */
  288. #define LARGE 30000
  289.  
  290. init_usq()
  291. {
  292.     int i, c;
  293.     char cc;
  294.  
  295.     char *p;
  296.     int numnodes;        /* size of decoding tree */
  297.     char origname[14];    /* Original file name without drive */
  298.  
  299.     /* Initialization */
  300.     init_cr();
  301.     init_huff();
  302.  
  303.     if(getw(in)!=RECOGNIZE) {
  304.         fprintf(stderr,"%s Not Squeezed\n", aname);
  305.         exit(1);
  306.     }
  307.     /* Process rest of header */
  308.     getw(in);    /* ignore checksum ... */
  309.  
  310.     /* Get original file name */
  311.     p = origname;    /* send it to array */
  312.     do {
  313.         *p = getc(in);
  314.     } while(*p++ != '\0');
  315.  
  316.     numnodes = getw(in);
  317.     if(numnodes < 0 || numnodes >= NUMVALS) {
  318.         fprintf(stderr, "%s has invalid decode tree size\n", aname);
  319.         exit(1);
  320.     }
  321.  
  322.     /* Initialize for possible empty tree (SPEOF only) */
  323.     dnode[0].children[0] = -(SPEOF + 1);
  324.     dnode[0].children[1] = -(SPEOF + 1);
  325.  
  326.     /* Get decoding tree from file */
  327.     for(i = 0; i < numnodes; ++i) {
  328.         dnode[i].children[0] = getw(in);
  329.         dnode[i].children[1] = getw(in);
  330.     }
  331. }
  332.  
  333.  
  334. /* initialize decoding functions */
  335.  
  336. init_cr()
  337. {
  338.     repct = 0;
  339. }
  340.  
  341. init_huff()
  342. {
  343.     bpos = 99;    /* force initial read */
  344. }
  345.  
  346. /* Get bytes with decoding - this decodes repetition,
  347.  * calls getuhuff to decode file stream into byte
  348.  * level code with only repetition encoding.
  349.  *
  350.  * The code is simple passing through of bytes except
  351.  * that DLE is encoded as DLE-zero and other values
  352.  * repeated more than twice are encoded as value-DLE-count.
  353.  */
  354.  
  355. int
  356. getcr()
  357. {
  358.     int c;
  359.  
  360.     if(repct > 0) {
  361.         /* Expanding a repeated char */
  362.         --repct;
  363.         return value;
  364.     } else {
  365.         /* Nothing unusual */
  366.         if((c = getuhuff()) != DLE) {
  367.             /* It's not the special delimiter */
  368.             value = c;
  369.             if(value == EOF)
  370.                 repct = LARGE;
  371.             return value;
  372.         } else {
  373.             /* Special token */
  374.             if((repct = getuhuff()) == 0)
  375.                 /* DLE, zero represents DLE */
  376.                 return DLE;
  377.             else {
  378.                 /* Begin expanding repetition */
  379.                 repct -= 2;    /* 2nd time */
  380.                 return value;
  381.             }
  382.         }
  383.     }
  384. }
  385.  
  386. /* Decode file stream into a byte level code with only
  387.  * repetition encoding remaining.
  388.  */
  389.  
  390. int
  391. getuhuff()
  392. {
  393.     /* Follow bit stream in tree to a leaf*/
  394.     inch = 0;    /* Start at root of tree */
  395.     do {
  396.         if(++bpos > 7) {
  397.             if((curin = getc(in)) == ERROR)
  398.                 return ERROR;
  399.             bpos = 0;
  400.             /* move a level deeper in tree */
  401.             inch = dnode[inch].children[1 & curin];
  402.         } else
  403.             inch = dnode[inch].children[1 & (curin >>= 1)];
  404.     } while(inch >= 0);
  405.  
  406.     /* Decode fake node index to original data value */
  407.     inch = -(inch + 1);
  408.     /* Decode special endfile token to normal EOF */
  409.     return (inch == SPEOF) ? EOF : inch;
  410.  
  411. }
  412.  
  413. /*
  414.  * uses algrithim of CRCK.COM previous to 5.0
  415.  */
  416. unsigned crck(crbuf, count, oldcrc)
  417. char *crbuf;
  418. unsigned oldcrc;
  419. {
  420.     unsigned n;
  421.     while (--count >= 0) {
  422.         n= (oldcrc << 1);
  423.         n = (n & 0xFF00) | (( n + *crbuf++ ) & 0xFF);
  424.         if(oldcrc & 0x8000)
  425.             n ^= 0xA097;
  426.         oldcrc = n;
  427.     }
  428.     return oldcrc;        
  429. }
  430.